/*
 *
 * Copyright (c) 2022 The Raptor Authors. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#ifndef RAPTOR_LITE_SRC_COMMON_MINI_CONTAINER_H_
#define RAPTOR_LITE_SRC_COMMON_MINI_CONTAINER_H_

#include <stddef.h>
#include <stdint.h>
#include <map>
#include <memory>
#include <list>
#include <utility>
#include <vector>

#include "raptor-lite/utils/atomic.h"
#include "raptor-lite/utils/mpscq.h"
#include "raptor-lite/utils/sync.h"
#include "raptor-lite/utils/thread.h"

#include "src/common/common.h"

namespace raptor {
class Connection;

struct MiniContainerMessageNode;

class MiniContainer {
public:
    explicit MiniContainer(uint16_t id);
    ~MiniContainer();

    raptor_error Init(int init_size, int max_size);
    raptor_error Start();
    void Shutdown();

    // recv epoll/iocp recv&send event
    void EventHandler(EventDetail *detail);

    // recv timer event
    void TimeoutChecking();
    void HeartBeatHandler(uint32_t index);

    void SendToEndpoint(uint32_t index, const Slice &s);
    void CloseEndpoint(uint32_t index, bool notify);
    std::shared_ptr<Connection> InsertEndpoint(Endpoint ep);

    void SetOption(Option *option) { option_ = option; }
    void SetMagic(uint16_t magic) { magic_ = magic; }
    uint16_t Id() const { return id_; }
    int32_t Count();

private:
    void MessageQueueThread(void *);
    void OnRecvSendEvent(EventDetail *detail);
    void OnHeartBeat(uint32_t index);
    void OnTimeoutChecking();
    void OnSendData(uint32_t index, const Slice &s);
    void OnCloseEndpoint(uint32_t index, bool notify);

    void OnErrorEvent(uint32_t index, int error_code);
    void OnRecvEvent(uint32_t index, EventDetail *);
    void OnSendEvent(uint32_t index, EventDetail *);

    void Dispatch(struct MiniContainerMessageNode *msg);

    void DeleteConnection(uint32_t index);
    void RefreshTime(uint32_t index);

private:
    // key: deadline, value: index
    using TimeoutRecordMap = std::multimap<int64_t, uint32_t>;

    // key: connection , value: iterator
    using ConnectionInfo = std::pair<std::shared_ptr<Connection>, TimeoutRecordMap::iterator>;

private:
    bool shutdown_;
    uint16_t id_;
    int32_t max_count_;

    uint16_t magic_;
    Option *option_;

    AtomicInt32 client_count_;
    AtomicInt64 last_check_time_;

    std::vector<ConnectionInfo> mgr_;
    Thread thd_;

    Mutex mtx_;

    AtomicInt64 count_;
    Mutex cmtx_;
    ConditionVariable cv_;
    MultiProducerSingleConsumerQueue mpscq_;

    TimeoutRecordMap timeout_records_;
    std::list<uint32_t> free_list_;
};

} // namespace raptor
#endif // RAPTOR_LITE_SRC_COMMON_MINI_CONTAINER_H_
